package cn.itcast.bos.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder.Operator;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.WildcardQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.bos.domain.take_delivery.Order;
import cn.itcast.bos.domain.take_delivery.WayBill;
import cn.itcast.bos.index.WayBillIndexRepository;
import cn.itcast.bos.repository.WayBillRepository;
import cn.itcast.bos.service.WayBillService;

@Service
@Transactional
public class WayBillServiceImpl implements WayBillService {

	@Autowired
	private WayBillRepository wayBillRepository;

	@Autowired
	private WayBillIndexRepository wayBillIndexRepository;

	/**
	 * 保存
	 */
	@Override
	public void save(WayBill model) {
		// 判断运单是不是存在
		WayBill persistWayBill = wayBillRepository.findByWayBillNum(model.getWayBillNum());
		// 运单不存在,执行保存
		if (persistWayBill == null) {
			model.setId(null);// 将id设置为null，目的是执行新增保存
			model.setSignStatus(1);// 运单签收状态，1表示待发货
			wayBillRepository.save(model);
			wayBillIndexRepository.save(model);
		}
		// 存在,执行修改
		else {
			if (persistWayBill.getSignStatus() == 1) {

				// 先去值,重新赋值
				Order order = persistWayBill.getOrder();
				// 将model中的属性值,copy到persistWayBill中
				try {
					BeanUtils.copyProperties(persistWayBill, model);
					persistWayBill.setOrder(order);
					persistWayBill.setSignStatus(1);
					wayBillIndexRepository.save(persistWayBill);// 更新

				} catch (IllegalAccessException | InvocationTargetException e) {
					e.printStackTrace();
					throw new RuntimeException(e.getMessage());
				}
			} else {
				// 运单状态已经在运输中,不能更改
				throw new RuntimeException("运单状态已经发出,无法修改保存!");
			}
		}
		// wayBillRepository.save(model);

	}
	
	/**
	 * 分页查询所有
	 */
	@Override
	public Page<WayBill> findAll(Pageable pageable) {
		Page<WayBill> page = wayBillRepository.findAll(pageable);
		return page;
	}

	/**
	 * 使用运单号查询运单
	 */
	@Override
	public WayBill findByWayBillNum(String wayBillNum) {
		return wayBillRepository.findByWayBillNum(wayBillNum);
	}

	/**
	 * 将数据库的数据同步到索引库
	 */
	// 启动定时任务 Quartz 每天定时同步 数据库信息和索引库信息
	@Override
	public void syncIndex() {
		// 查询数据库
		List<WayBill> wayBills = wayBillRepository.findAll();
		// 同步索引库
		wayBillIndexRepository.save(wayBills);
	}

	/**
	 * 如果没有指定查询条件：从数据库中查询所有
	 * 如果指定条件查询：从索引库中查询结果
	 */
	@Override
	public Page<WayBill> findAll(WayBill wayBill, Pageable pageable) {
		// return wayBillRepository.findAll(pageable);
		// 判断WayBill中添加是否存在，全部通过索引库中检索
		if (StringUtils.isBlank(wayBill.getWayBillNum()) && StringUtils.isBlank(wayBill.getSendAddress())
				&& StringUtils.isBlank(wayBill.getRecAddress()) && StringUtils.isBlank(wayBill.getSendProNum())
				&& (wayBill.getSignStatus() == null || wayBill.getSignStatus() == 0)) {
			// 无条件查询,查询数据库
			return wayBillIndexRepository.findAll(pageable);
		} else {
			BoolQueryBuilder query = new BoolQueryBuilder();
			// 向组合查询条件中添加条件
			if (StringUtils.isNoneBlank(wayBill.getWayBillNum())) {
				QueryBuilder queryBuilder = new TermQueryBuilder("wayBillNum", wayBill.getWayBillNum());
				query.must(queryBuilder);
			}
			// 发货地的模糊查询
			if (StringUtils.isNoneBlank(wayBill.getSendAddress())) {
				// 情况一：发货地输入“北”，查询索引库词条的一部分，可以使用模糊匹配词条查询
				QueryBuilder queryBuilder = new WildcardQueryBuilder("sendAddress",
						"*" + wayBill.getSendAddress() + "*");
				// 情况二：发货地输入“北京市海淀区”，是多个词条组合，进行分词后，每个词条匹配查询
				QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(wayBill.getSendAddress())
						.field("sendAddress").defaultOperator(Operator.AND);
				BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
				boolQueryBuilder.should(queryStringQueryBuilder).should(queryBuilder);
				query.must(boolQueryBuilder);
			}
			if (StringUtils.isNotBlank(wayBill.getRecAddress())) {
				// 收货地 模糊查询
				// 情况一：收货地输入“北”，查询索引库词条的一部分，可以使用模糊匹配词条查询
				QueryBuilder wildcardQuery = new WildcardQueryBuilder("recAddress",
						"*" + wayBill.getRecAddress() + "*");
				// 情况二：收货地输入“北京市海淀区”，是多个词条组合，进行分词后，每个词条匹配查询
				QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(wayBill.getRecAddress())
						.field("recAddress").defaultOperator(Operator.AND);// 分词后查询，使用and连接
				// 上面的两种情况，有一种满足即可，使用bool查询的or关系
				BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
				boolQueryBuilder.should(wildcardQuery).should(queryStringQueryBuilder);
				query.must(boolQueryBuilder);
			}
			if (StringUtils.isNotBlank(wayBill.getSendProNum())) {
				// 速运类型的等值查询
				QueryBuilder queryBuilder = new TermQueryBuilder("sendProNum", wayBill.getSendProNum());
				query.must(queryBuilder);
			}
			if (wayBill.getSignStatus() != null && wayBill.getSignStatus() != 0) {
				// 签收状态查询
				QueryBuilder termQuery = new TermQueryBuilder("signStatus", wayBill.getSignStatus());
				query.must(termQuery);

			}
			NativeSearchQuery searchQuery = new NativeSearchQuery(query);
			searchQuery.setPageable(pageable);// 分页效果
			return wayBillIndexRepository.search(searchQuery);

		}

	}

	/**
	 * 导出excel报表/pdf报表（从数据库检索）（本例：查询所有，查询数据库；指定条件查询，查询索引库）
	 */
	@Override
	public List<WayBill> findWayBills(WayBill wayBill) {
		// 如果没有指定条件，此时可以查询数据库，获取所有的数据
				if(StringUtils.isBlank(wayBill.getWayBillNum())
						&& StringUtils.isBlank(wayBill.getSendAddress())
						&& StringUtils.isBlank(wayBill.getRecAddress())
						&& StringUtils.isBlank(wayBill.getSendProNum())
						&& (wayBill.getSignStatus()==null || wayBill.getSignStatus()==0)){
					return wayBillRepository.findAll();
				}else {
					BoolQueryBuilder query = new BoolQueryBuilder();
					// 向组合查询条件中添加条件
					if (StringUtils.isNoneBlank(wayBill.getWayBillNum())) {
						QueryBuilder queryBuilder = new TermQueryBuilder("wayBillNum", wayBill.getWayBillNum());
						query.must(queryBuilder);
					}
					// 发货地的模糊查询
					if (StringUtils.isNoneBlank(wayBill.getSendAddress())) {
						// 情况一：发货地输入“北”，查询索引库词条的一部分，可以使用模糊匹配词条查询
						QueryBuilder queryBuilder = new WildcardQueryBuilder("sendAddress",
								"*" + wayBill.getSendAddress() + "*");
						// 情况二：发货地输入“北京市海淀区”，是多个词条组合，进行分词后，每个词条匹配查询
						QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(wayBill.getSendAddress())
								.field("sendAddress").defaultOperator(Operator.AND);
						BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
						boolQueryBuilder.should(queryStringQueryBuilder).should(queryBuilder);
						query.must(boolQueryBuilder);
					}
					if (StringUtils.isNotBlank(wayBill.getRecAddress())) {
						// 收货地 模糊查询
						// 情况一：收货地输入“北”，查询索引库词条的一部分，可以使用模糊匹配词条查询
						QueryBuilder wildcardQuery = new WildcardQueryBuilder("recAddress",
								"*" + wayBill.getRecAddress() + "*");
						// 情况二：收货地输入“北京市海淀区”，是多个词条组合，进行分词后，每个词条匹配查询
						QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(wayBill.getRecAddress())
								.field("recAddress").defaultOperator(Operator.AND);// 分词后查询，使用and连接
						// 上面的两种情况，有一种满足即可，使用bool查询的or关系
						BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
						boolQueryBuilder.should(wildcardQuery).should(queryStringQueryBuilder);
						query.must(boolQueryBuilder);
					}
					if (StringUtils.isNotBlank(wayBill.getSendProNum())) {
						// 速运类型的等值查询
						QueryBuilder queryBuilder = new TermQueryBuilder("sendProNum", wayBill.getSendProNum());
						query.must(queryBuilder);
					}
					if (wayBill.getSignStatus() != null && wayBill.getSignStatus() != 0) {
						// 签收状态查询
						QueryBuilder termQuery = new TermQueryBuilder("signStatus", wayBill.getSignStatus());
						query.must(termQuery);

					}
					NativeSearchQuery searchQuery = new NativeSearchQuery(query);
					Pageable pageable = new PageRequest(0, 10000);
					searchQuery.setPageable(pageable);// 分页效果
					return wayBillIndexRepository.search(searchQuery).getContent();
					
				}
		
	}

	@Override
	public List<Object[]> charWayBill() {
		return wayBillRepository.findBySignStatus();
	}


}
